package com.dashan.backend;

import static com.dashan.Constants.ALL_FRIEND_GROUP_NAME;
import static com.dashan.Constants.ALL_FRIEND_GROUP_PERMISSION;
import static com.dashan.Constants.PUBLIC_GROUP_NAME;
import static com.dashan.Constants.PUBLIC_GROUP_PERMISSION;

import java.util.Date;

import javax.jdo.JDOObjectNotFoundException;

import com.dashan.backend.datastore.DsFriend;
import com.dashan.backend.datastore.DsFriendGroup;
import com.dashan.backend.datastore.DsFriendInvitation;
import com.dashan.backend.datastore.DsUser;
import com.dashan.backend.datastore.FriendGroupDao;
import com.dashan.backend.datastore.FriendInvitationDao;
import com.dashan.backend.datastore.UserDao;
import com.google.appengine.api.datastore.Key;

public class FriendManager {

    /**
     * User "from" want to be the friend of user "to".
     * 
     * @param from the user want to be the user "to"'s friend
     * @throws JDOObjectNotFoundException if one of from/to is not exist
     * @throws DashanException 
     */
    public static void inviteFriend(String from, String to, String message) 
        throws JDOObjectNotFoundException, DashanException{
        UserDao userDao = new UserDao();
        FriendInvitationDao friendInvitationDao = new FriendInvitationDao();
        try {
            DsUser userFrom = userDao.getUser(from);
            userDao.getUser(to);
            
            if (userFrom.getFriend(to) != null) {
                throw new DashanException(String.format("%s is already a friend of %s", from, to));
            }
            
            DsFriendInvitation dsRequest = new DsFriendInvitation(from, to, message, new Date());
            friendInvitationDao.addFriendInvitation(dsRequest);
        } finally {
            friendInvitationDao.commit();
            userDao.commit();
        }
    }
    
    public static void acceptInvitation(String from, String to) throws DashanException {
        UserDao userDao = new UserDao();
        FriendInvitationDao friendInvitationDao = new FriendInvitationDao();
        try {
            DsUser userFrom = userDao.getUser(from);
            DsUser userTo = userDao.getUser(to);
            friendInvitationDao.removeFriendInvitation(from, to);            
            FriendManager.addFriend(userFrom, to);
            FriendManager.addFriend(userTo, from);
        } catch (JDOObjectNotFoundException e) {
            throw new DashanException("No invitation found!");
        } finally {
            friendInvitationDao.commit();
            userDao.commit();
        }
    }
    
    public static void addFriend(DsUser user, String friendName) throws DashanException {
        user.addFriend(friendName);
        user.getFriend(friendName).addToGroup(user.getGroup(ALL_FRIEND_GROUP_NAME).getKey());
    }
    
    public static void initializeUserGroup(DsUser user) throws DashanException {
        user.addGroup(PUBLIC_GROUP_NAME, PUBLIC_GROUP_PERMISSION);
        user.addGroup(ALL_FRIEND_GROUP_NAME, ALL_FRIEND_GROUP_PERMISSION);
    }
    
    public static void createGroup(DsUser user, String groupName, long permission) 
        throws DashanException {
        user.addGroup(groupName, permission);
    }
    
    public static void deleteGroup(DsUser user, String groupName) throws DashanException {
        if (groupName.compareTo(PUBLIC_GROUP_NAME) == 0) {
            throw new DashanException("Public group cannot be removed!");
        }
        if (groupName.compareTo(ALL_FRIEND_GROUP_NAME) == 0) {
            throw new DashanException("All friend group cannot be removed!");
        }
        
        Key groupKey = user.getGroup(groupName).getKey();
        for (DsFriend f : user.getFriends()) {
            removeFriendFromGroup(f, groupKey);
        }
        DsFriendGroup g = user.getGroup(groupName);
        if (g == null) {
            throw new DashanException("Group not found!" + groupName);
        }
        user.removeGroup(g);
    }
    
    public static void removeFriendFromGroup(DsFriend dsFriend, Key groupKey) 
        throws DashanException {
        FriendGroupDao dao = new FriendGroupDao();
        try {
            String groupName = dao.getGroup(groupKey).getGroupName();
            if (groupName.compareTo(ALL_FRIEND_GROUP_NAME) == 0) {
                throw new DashanException(String.format("'%s' group cannot be removed from friend", 
                        ALL_FRIEND_GROUP_NAME));
            }
            dsFriend.removeFromGroup(groupKey);
        } finally {
            dao.commit();
        }
    }
    
    public static void addFriendToGroup(DsUser user, String friendName, String groupName) throws DashanException {
        DsFriendGroup g = user.getGroup(groupName);
        if (g == null) {
            throw new DashanException("Group not found: " + groupName);
        }
        
        DsFriend f = user.getFriend(friendName);
        if (f == null) {
            throw new DashanException("Friend not found: " + friendName);
        }
        
        f.addToGroup(g.getKey());
    }
}

